using DocumentCreationSystem.Models;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace DocumentCreationSystem.Services;

/// <summary>
/// 智谱AI服务实现
/// </summary>
public class ZhipuAIService : IAIService
{
    private readonly IConfiguration _configuration;
    private readonly ILogger _logger;
    private readonly HttpClient _httpClient;
    private readonly string _apiKey;
    private readonly string _baseUrl;
    private readonly List<AIModel> _availableModels;
    private AIModel? _currentModel;

    public ZhipuAIService(IConfiguration configuration, ILogger logger)
    {
        _configuration = configuration;
        _logger = logger;
        _httpClient = new HttpClient();

        _apiKey = configuration["ApiKey"] ?? "";
        _baseUrl = configuration["BaseUrl"] ?? "https://open.bigmodel.cn/api/paas/v4";

        _availableModels = new List<AIModel>();

        InitializeModels();
        ConfigureHttpClient();
    }

    private void InitializeModels()
    {
        // 智谱AI可用模型列表（根据最新API限制）
        _availableModels.AddRange(new[]
        {
            new AIModel
            {
                Id = "GLM-4-Flash-250414",
                Name = "GLM-4-Flash-250414",
                Provider = "ZhipuAI",
                Description = "对话模型 - 主要用于文本创作",
                IsAvailable = true,
                MaxTokens = 8192
            },
            new AIModel
            {
                Id = "GLM-4.1V-Thinking",
                Name = "GLM-4.1V-Thinking",
                Provider = "ZhipuAI",
                Description = "视觉推理模型 - 支持图像理解和深度推理",
                IsAvailable = true,
                MaxTokens = 8192
            },
            new AIModel
            {
                Id = "GLM-4.1V-Thinking-Flash",
                Name = "GLM-4.1V-Thinking-Flash",
                Provider = "ZhipuAI",
                Description = "视觉推理模型(快速版) - 支持图像理解和推理",
                IsAvailable = true,
                MaxTokens = 8192
            },
            new AIModel
            {
                Id = "GLM-4V-Flash",
                Name = "GLM-4V-Flash",
                Provider = "ZhipuAI",
                Description = "图像理解模型 - 专门用于图像分析",
                IsAvailable = true,
                MaxTokens = 8192
            },
            new AIModel
            {
                Id = "GLM-Z1-Flash",
                Name = "GLM-Z1-Flash",
                Provider = "ZhipuAI",
                Description = "推理模型 - 适合复杂逻辑推理",
                IsAvailable = true,
                MaxTokens = 8192
            },
            new AIModel
            {
                Id = "Cogview-3-Flash",
                Name = "Cogview-3-Flash",
                Provider = "ZhipuAI",
                Description = "图像生成模型 - 用于生成图像",
                IsAvailable = true,
                MaxTokens = 4096
            },
            new AIModel
            {
                Id = "CogVideoX-Flash",
                Name = "CogVideoX-Flash",
                Provider = "ZhipuAI",
                Description = "视频生成模型 - 用于生成视频",
                IsAvailable = true,
                MaxTokens = 4096
            }
        });

        // 设置默认模型
        var defaultModelId = _configuration["DefaultModel"] ?? "GLM-4-Flash-250414";
        _currentModel = _availableModels.FirstOrDefault(m => m.Id == defaultModelId) ?? _availableModels.First();
    }

    private void ConfigureHttpClient()
    {
        _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}");
        _httpClient.DefaultRequestHeaders.Add("User-Agent", "DocumentCreationSystem/1.0");
        _httpClient.Timeout = TimeSpan.FromSeconds(120); // 120秒，符合API请求最佳实践
    }

    public async Task<List<AIModel>> GetAvailableModelsAsync()
    {
        try
        {
            // 检查模型可用性
            foreach (var model in _availableModels)
            {
                model.IsAvailable = await CheckModelAvailabilityAsync(model.Id);
            }

            return _availableModels.Where(m => m.IsAvailable).ToList();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取智谱AI模型列表失败");
            return _availableModels; // 返回默认列表
        }
    }

    private async Task<bool> CheckModelAvailabilityAsync(string modelId)
    {
        try
        {
            var request = new
            {
                model = modelId,
                messages = new[]
                {
                    new { role = "user", content = "test" }
                },
                max_tokens = 1
            };

            var json = JsonSerializer.Serialize(request);
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            var response = await _httpClient.PostAsync($"{_baseUrl}/chat/completions", content);
            return response.IsSuccessStatusCode;
        }
        catch
        {
            return false;
        }
    }

    public async Task<bool> SetCurrentModelAsync(string modelId)
    {
        var model = _availableModels.FirstOrDefault(m => m.Id == modelId);
        if (model == null)
        {
            _logger.LogWarning($"智谱AI模型不存在: {modelId}");
            return false;
        }

        // 先设置模型，然后可选地检查可用性
        _currentModel = model;
        _logger.LogInformation($"设置智谱AI模型: {model.Name}");

        // 异步检查模型可用性，但不阻塞设置过程
        _ = Task.Run(async () =>
        {
            try
            {
                var isAvailable = await CheckModelAvailabilityAsync(modelId);
                if (isAvailable)
                {
                    _logger.LogInformation($"智谱AI模型 {model.Name} 可用性验证成功");
                }
                else
                {
                    _logger.LogWarning($"智谱AI模型 {model.Name} 可用性验证失败，但模型已设置");
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, $"智谱AI模型 {model.Name} 可用性检查异常，但模型已设置");
            }
        });

        return true;
    }

    public AIModel? GetCurrentModel()
    {
        return _currentModel;
    }

    public async Task<string> GenerateTextAsync(string prompt, int maxTokens = 2000, float temperature = 0.7f)
    {
        if (_currentModel == null)
        {
            throw new InvalidOperationException("未设置当前智谱AI模型");
        }

        const int maxRetries = 3;
        var retryDelay = TimeSpan.FromSeconds(2);

        for (int attempt = 1; attempt <= maxRetries; attempt++)
        {
            try
            {
                var request = new
                {
                    model = _currentModel.Id,
                    messages = new[]
                    {
                        new { role = "user", content = prompt }
                    },
                    max_tokens = Math.Min(maxTokens, _currentModel.MaxTokens),
                    temperature = Math.Max(0.1f, Math.Min(1.0f, temperature)),
                    stream = false
                };

                var json = JsonSerializer.Serialize(request);
                var content = new StringContent(json, Encoding.UTF8, "application/json");

                using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
                var response = await _httpClient.PostAsync($"{_baseUrl}/chat/completions", content, cts.Token);

                if (!response.IsSuccessStatusCode)
                {
                    var errorContent = await response.Content.ReadAsStringAsync();
                    var errorMessage = $"智谱AI API调用失败 (状态码: {response.StatusCode})";

                    // 尝试解析错误详情
                    try
                    {
                        var errorJson = JsonSerializer.Deserialize<JsonElement>(errorContent);
                        if (errorJson.TryGetProperty("error", out var errorElement) &&
                            errorElement.TryGetProperty("message", out var messageElement))
                        {
                            errorMessage += $" - {messageElement.GetString()}";
                        }
                    }
                    catch
                    {
                        errorMessage += $" - {errorContent}";
                    }

                    throw new HttpRequestException(errorMessage);
                }

                var responseJson = await response.Content.ReadAsStringAsync();
                var result = JsonSerializer.Deserialize<ZhipuAIResponse>(responseJson);

                if (result?.Choices?.Length > 0)
                {
                    var generatedText = result.Choices[0].Message.Content ?? "";
                    _logger.LogInformation($"智谱AI文本生成成功，长度: {generatedText.Length}");
                    return generatedText;
                }

                throw new InvalidOperationException("智谱AI返回空响应");
            }
            catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
            {
                _logger.LogWarning($"智谱AI请求超时 (尝试 {attempt}/{maxRetries})");
                if (attempt == maxRetries)
                {
                    throw new TimeoutException($"智谱AI请求超时，已重试 {maxRetries} 次");
                }
            }
            catch (HttpRequestException ex) when (attempt < maxRetries)
            {
                _logger.LogWarning($"智谱AI网络请求失败 (尝试 {attempt}/{maxRetries}): {ex.Message}");
                await Task.Delay(retryDelay * attempt);
                continue;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"智谱AI文本生成失败 (尝试 {attempt}/{maxRetries})");
                if (attempt == maxRetries)
                {
                    throw new InvalidOperationException($"智谱AI文本生成失败: {ex.Message}", ex);
                }
                await Task.Delay(retryDelay * attempt);
            }
        }

        throw new InvalidOperationException("智谱AI文本生成失败，已达到最大重试次数");
    }

    public async Task<string> PolishTextAsync(string text, string style = "通用")
    {
        var prompt = $@"请对以下文本进行润色，要求：
1. 保持原文的核心意思不变
2. 提升文字的流畅性和可读性
3. 润色风格：{style}
4. 只返回润色后的文本，不要添加任何解释

原文：
{text}";

        return await GenerateTextAsync(prompt, 4000, 0.3f);
    }

    public async Task<string> ExpandTextAsync(string text, int targetLength, string? context = null)
    {
        var contextInfo = !string.IsNullOrEmpty(context) ? $"\n\n上下文信息：\n{context}" : "";
        
        var prompt = $@"请对以下文本进行扩写，要求：
1. 保持原文的核心内容和风格
2. 增加细节描述、情感表达和场景渲染
3. 目标长度约{targetLength}字
4. 确保扩写内容与原文自然衔接
5. 只返回扩写后的完整文本{contextInfo}

原文：
{text}";

        return await GenerateTextAsync(prompt, Math.Max(targetLength + 1000, 4000), 0.7f);
    }

    public async Task<string> GenerateChapterAsync(string outline, string? context = null, int targetWordCount = 6500)
    {
        var contextInfo = !string.IsNullOrEmpty(context) ? $"\n\n=== 参考信息 ===\n{context}" : "";

        var prompt = $@"你是一位专业的小说作家，现在需要根据章节细纲创作小说章节内容。

=== 重要：必须严格按照以下章节细纲进行创作 ===
{outline}

=== 字数要求（必须严格遵守）===
**目标字数：{targetWordCount}字**
- 最少不能低于{(int)(targetWordCount * 0.9)}字
- 最多不能超过{(int)(targetWordCount * 1.1)}字
- 请在创作过程中时刻关注字数，确保达到目标字数
- 如果内容不够，请增加细节描写、心理描写、环境描写等
- 如果内容过多，请适当精简，但不能删除关键情节

=== 创作要求 ===
1. **严格按照上述章节细纲的场景、人物、剧情发展进行创作**
2. **必须达到{targetWordCount}字的目标字数，这是硬性要求**
3. 保持小说的连贯性和可读性
4. 注意人物性格和情节发展的一致性
5. 只返回章节正文内容，不要标题和其他说明
6. **确保章节内容与细纲中描述的场景、冲突、人物发展完全一致**
7. **在创作时要充分展开情节，增加对话、动作、心理、环境等描写来达到字数要求**{contextInfo}

=== 创作指导 ===
为了达到{targetWordCount}字的要求，请注意：
- 详细描写人物的外貌、表情、动作
- 丰富环境和场景的描述
- 增加人物内心独白和心理活动
- 扩展对话内容，让对话更自然生动
- 添加适当的背景信息和回忆片段
- 细致描写战斗、冲突等关键场面

请开始创作章节正文：";

        return await GenerateTextAsync(prompt, Math.Max(targetWordCount + 2000, 8000), 0.8f);
    }

    public async Task<ConsistencyCheckResult> CheckConsistencyAsync(string currentText, string previousContext)
    {
        var prompt = $@"请检查以下当前文本与之前上下文的一致性，重点关注：
1. 人物性格和行为是否一致
2. 情节发展是否合理
3. 时间线是否正确
4. 设定是否矛盾

请以JSON格式返回检查结果，格式如下：
{{
  ""isConsistent"": true/false,
  ""confidenceScore"": 0.0-1.0,
  ""issues"": [""问题描述1"", ""问题描述2""],
  ""suggestions"": [""建议1"", ""建议2""]
}}

之前的上下文：
{previousContext}

当前文本：
{currentText}";

        try
        {
            var response = await GenerateTextAsync(prompt, 2000, 0.3f);

            // 尝试解析JSON响应
            var jsonStart = response.IndexOf('{');
            var jsonEnd = response.LastIndexOf('}');

            if (jsonStart >= 0 && jsonEnd > jsonStart)
            {
                var jsonStr = response.Substring(jsonStart, jsonEnd - jsonStart + 1);
                var result = JsonSerializer.Deserialize<ConsistencyCheckResult>(jsonStr, new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                });

                if (result != null)
                {
                    return result;
                }
            }

            // 如果JSON解析失败，返回默认结果
            return new ConsistencyCheckResult
            {
                IsConsistent = true,
                ConfidenceScore = 0.5f,
                Issues = new List<string> { "无法解析一致性检查结果" },
                Suggestions = new List<string> { "建议人工检查文本一致性" }
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "智谱AI一致性检查失败");
            return new ConsistencyCheckResult
            {
                IsConsistent = false,
                ConfidenceScore = 0.0f,
                Issues = new List<string> { $"检查过程出错: {ex.Message}" },
                Suggestions = new List<string> { "建议重新进行一致性检查" }
            };
        }
    }

    public async Task<string> GenerateOutlineAsync(string description, string outlineType)
    {
        var prompt = outlineType.ToLower() switch
        {
            "全书" => $@"请根据以下描述生成小说全书大纲，要求：
1. 包含主要情节线和人物关系
2. 分为若干卷或部分
3. 每部分包含主要事件和发展
4. 保持情节的连贯性和吸引力

描述：{description}",

            "卷宗" => $@"请根据以下描述生成卷宗大纲，要求：
1. 详细的章节安排
2. 每章的主要内容和目标
3. 人物发展和情节推进
4. 保持节奏感和悬念

描述：{description}",

            "章节" => $@"请根据以下描述生成章节细纲，要求：
1. 详细的场景安排
2. 人物对话和行动
3. 情节发展的关键点
4. 字数约6500字的内容规划

描述：{description}",

            _ => $@"请根据以下描述生成{outlineType}大纲：

描述：{description}"
        };

        return await GenerateTextAsync(prompt, 4000, 0.8f);
    }

    public async Task<List<CharacterInfo>> ExtractCharacterInfoAsync(string text)
    {
        var prompt = $@"请从以下文本中提取角色信息，以JSON数组格式返回，每个角色包含：
- name: 角色名称
- description: 角色描述
- attributes: 角色属性（如境界、年龄等）
- skills: 技能列表
- equipment: 装备列表

格式示例：
[
  {{
    ""name"": ""角色名"",
    ""description"": ""角色描述"",
    ""attributes"": {{""境界"": ""筑基期"", ""年龄"": ""18岁""}},
    ""skills"": [""技能1"", ""技能2""],
    ""equipment"": [""装备1"", ""装备2""]
  }}
]

文本内容：
{text}";

        try
        {
            var response = await GenerateTextAsync(prompt, 3000, 0.3f);

            // 尝试解析JSON响应
            var jsonStart = response.IndexOf('[');
            var jsonEnd = response.LastIndexOf(']');

            if (jsonStart >= 0 && jsonEnd > jsonStart)
            {
                var jsonStr = response.Substring(jsonStart, jsonEnd - jsonStart + 1);
                var characters = JsonSerializer.Deserialize<List<CharacterInfo>>(jsonStr, new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                });

                return characters ?? new List<CharacterInfo>();
            }

            return new List<CharacterInfo>();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "智谱AI角色信息提取失败");
            return new List<CharacterInfo>();
        }
    }
}

/// <summary>
/// 智谱AI API响应模型
/// </summary>
public class ZhipuAIResponse
{
    [JsonPropertyName("choices")]
    public ZhipuAIChoice[]? Choices { get; set; }
}

public class ZhipuAIChoice
{
    [JsonPropertyName("message")]
    public ZhipuAIMessage Message { get; set; } = new();
}

public class ZhipuAIMessage
{
    [JsonPropertyName("content")]
    public string? Content { get; set; }
}
